<?php
/**
 * 定时任务进程
 * 用于处理会员自动到期和续费等后台任务
 */

namespace app\process;

use support\Log;

class CronProcess
{
    /**
     * @var array 定时任务配置
     */
    protected static $crontab = [];
    
    /**
     * 构造函数
     */
    public function __construct()
    {
        // 加载定时任务配置
        $crontabConfig = config('crontab', []);
        self::$crontab = $crontabConfig;
    }
    
    /**
     * 启动定时任务
     */
    public function onWorkerStart()
    {
        Log::info('Cron process started');
        
        // 每分钟检查一次定时任务
        \Workerman\Timer::add(60, function () {
            $this->checkCrontab();
        });
    }
    
    /**
     * 检查定时任务
     */
    protected function checkCrontab()
    {
        $now = time();
        $currentTime = date('Y-m-d H:i:s', $now);
        
        foreach (self::$crontab as $name => $task) {
            if (!isset($task['timer']) || !isset($task['task'])) {
                continue;
            }
            
            // 检查是否应该执行
            if ($this->shouldRun($task['timer'], $now)) {
                try {
                    Log::info("Executing scheduled task: {$name}");
                    call_user_func($task['task']);
                    Log::info("Scheduled task completed: {$name}");
                } catch (\Exception $e) {
                    Log::error("Scheduled task failed: {$name} - " . $e->getMessage());
                }
            }
        }
    }
    
    /**
     * 检查是否应该运行定时任务
     */
    protected function shouldRun($timer, $now)
    {
        // 解析cron表达式
        $parts = explode(' ', $timer);
        if (count($parts) !== 5) {
            return false;
        }
        
        list($minute, $hour, $day, $month, $weekday) = $parts;
        
        // 获取当前时间信息
        $currentMinute = (int)date('i', $now);
        $currentHour = (int)date('G', $now);
        $currentDay = (int)date('j', $now);
        $currentMonth = (int)date('n', $now);
        $currentWeekday = (int)date('w', $now);
        
        // 检查分钟
        if (!$this->checkTimePart($minute, $currentMinute)) {
            return false;
        }
        
        // 检查小时
        if (!$this->checkTimePart($hour, $currentHour)) {
            return false;
        }
        
        // 检查日期
        if (!$this->checkTimePart($day, $currentDay)) {
            return false;
        }
        
        // 检查月份
        if (!$this->checkTimePart($month, $currentMonth)) {
            return false;
        }
        
        // 检查星期
        if (!$this->checkTimePart($weekday, $currentWeekday)) {
            return false;
        }
        
        return true;
    }
    
    /**
     * 检查时间部分
     */
    protected function checkTimePart($expression, $current)
    {
        // 处理通配符
        if ($expression === '*') {
            return true;
        }
        
        // 处理列表 (例如: 1,3,5)
        if (strpos($expression, ',') !== false) {
            $values = explode(',', $expression);
            return in_array($current, $values);
        }
        
        // 处理范围 (例如: 1-5)
        if (strpos($expression, '-') !== false) {
            list($start, $end) = explode('-', $expression);
            return $current >= $start && $current <= $end;
        }
        
        // 处理步长 (例如: */5)
        if (strpos($expression, '/') !== false) {
            list($range, $step) = explode('/', $expression);
            if ($range === '*') {
                return $current % $step === 0;
            }
        }
        
        // 处理具体值
        return $current == $expression;
    }
}